import javax.microedition.lcdui.Graphics;

public class Hero {
    // coords
    public static int m_nPosX = 0; // Marv's position
    public static int m_nPosY = 0;

    public static int m_nTmpPosX = 0;
    public static int m_nTmpPosY = 0;

    public static int m_nTotalDropHeight = 0;

    public static boolean m_blDirRight = true;
    public static byte m_VDirection;

    // speed
    public static int m_nSpeedLeft;
    public static int m_nSpeedRight;
    public static long m_nSpeedUp;
    public static long m_nSpeedDown;
    public static int m_nSpeed45Degree;
    public static boolean m_bJumpEnable;
    public static boolean m_bTransporter;
    public static boolean m_bCrashingPlatform;
    public static byte m_bLastTimeTick;
    public static byte m_nFlightDir;

    // animations
    public static boolean m_blChangeAnimEnable;
    public static int m_nCurAnimID;
    public static Animation animationCurrent;
    public static int m_nDeathTicks = 0;

    // animation's objects
    public static Animation animGoLeft = new Animation(AnimID.AnimID_WalkLeft);
    public static Animation animGoRight = new Animation(AnimID.AnimID_WalkRight);

    public static Animation animJumpRight = new Animation(AnimID.AnimID_JumpRight);
    public static Animation animJumpLeft = new Animation(AnimID.AnimID_JumpLeft);

    public static Animation animFall = new Animation(AnimID.AnimID_Fall);

    public static Animation animDeath = new Animation(AnimID.AnimID_Death);
    //#if !IMGGROUP_12x12xLimited
        public static Animation animFallDeath = new Animation(AnimID.AnimID_FallDeath);
        public static Animation animFireDeath = new Animation(AnimID.AnimID_FireDeath);
        public static Animation animTODeath = new Animation(AnimID.AnimID_TODeath);

        public static Animation animTurn = new Animation(AnimID.AnimID_MarvTurn);

        public static Animation animCannonChRight = new Animation(AnimID.AnimID_MarvLoadRight);
        public static Animation animCannonChLeft = new Animation(AnimID.AnimID_MarvLoadLeft);
    //#endif
    public static Animation animCannonFlying = new Animation(AnimID.AnimID_MarvFlying);

    public static Animation animTeleport = new Animation(AnimID.AnimID_TeleportMarv);

    public static Animation animItemDynamite = new Animation(AnimID.AnimID_Bomb);
    public static Animation animItemPickAxeleft = new Animation(AnimID.AnimID_PALeft);
    public static Animation animItemPickAxeRight = new Animation(AnimID.AnimID_PARight);

    public static Animation animClimbLadder = new Animation(AnimID.AnimID_ClimbLadder);
    public static Animation animLadderStartFinish = new Animation(AnimID.AnimID_LadderStartFinish);

    // gameplay
    public static int m_nLevel = 0;
    public static int m_nLevelMax = 0; // maximum level-number
    public static int m_nKeybMode;

    public static boolean m_blVisible = true;

    public static byte m_bJumper = 0;

    public static int objCurrentIndex;
    public static int objTeleportNextIndex;

    public static int m_nLives = 0;
    public static int m_nTotalScores = 0;

    public static boolean m_blDynamite = false;
    public static int m_nPickAxe = 0;

    public static int m_nImmortalTicks = 0;

    public static boolean timeAlarm = false;

    // cannon help
    private static byte cannonCurMess = 0;
    private static int cannonMessQueue[] = {-1, -1, -1};
    private static int cannonShowTime = 0;
    private static int cannonWaitTime = 0;

    /**
     *
     */
    public static void CleanUp() {
        m_nLives = c_nMaxLives;
        m_nTotalScores = 0;
        m_nImmortalTicks = 0;
    }

    /**
     *
     */
    public static boolean Init() {
        m_blVisible = true;
        m_nKeybMode = nModeNormal;
        m_bLastTimeTick = 0;

        m_nPosX = GameWorld.nStartX;     // point of foot
        m_nPosY = GameWorld.nStartY;     // point of foot

        m_nTmpPosX = m_nPosX; // point of foot
        m_nTmpPosY = m_nPosY;

        m_blDynamite = false;
        m_nPickAxe = 0;

        // speeds
        m_nSpeedLeft = 0;
        m_nSpeedRight = 0;
        m_nSpeedUp = 0;
        m_nSpeedDown = 0;
        m_bJumpEnable = false;
        m_bTransporter = false;
        m_bCrashingPlatform = false;
        m_nFlightDir = Constants.DIRECTION_FLY_NONE;

        m_nTotalDropHeight = 0;
        m_nDeathTicks = 0;

        m_blChangeAnimEnable = true;
        setAnim(c_nAnimID_Idle);

        objCurrentIndex = -1;
        objTeleportNextIndex = -1;

        //#if SOUND_NOKIA_RT || SOUND_MMAPI || SAMSUNG_MMF || SHARP_MMF
            MTMCanvas.soundStop(MTMCanvas.soundId);

            if (m_nImmortalTicks > 0) {
                MTMCanvas.soundPlay(Constants.SOUND_NEW_LIFE);
            }
        //#endif

        timeAlarm = false;

        setCannonMessQueue(LevObj.c_bCannonState_Charging, true);

        return true;
    }

    /**
     *
     */
    private static void setCannonMessQueue(int phase, boolean wait) {
        switch (phase) {
            case LevObj.c_bCannonState_Charging:
                cannonMessQueue[0] = StringsID.nStrID_CannonStart;
                cannonMessQueue[1] = -1;
                cannonMessQueue[2] = -1;
            break;
            
            case LevObj.c_bCannonState_ClimbIn:
                cannonMessQueue[0] = StringsID.nStrID_CannonPower;
                cannonMessQueue[1] = StringsID.nStrID_CannonIn;
                cannonMessQueue[2] = StringsID.nStrID_CannonOut;
            break;

            case LevObj.c_bCannonState_Move:
                cannonMessQueue[0] = StringsID.nStrID_CannonMove;
                cannonMessQueue[1] = StringsID.nStrID_CannonAiming;
                cannonMessQueue[2] = StringsID.nStrID_CannonOut;
            break;

            case LevObj.c_bCannonState_Aiming:
                cannonMessQueue[0] = StringsID.nStrID_CannonFire;
                cannonMessQueue[1] = StringsID.nStrID_CannonOut;
                cannonMessQueue[2] = -1;
            break;
        }

        cannonCurMess = 0;
        cannonShowTime = 0;
      
        if (wait)
            cannonWaitTime = 0;
        else
            cannonWaitTime = c_nMessWaitTime;
    }

    /**
     *
     */
    public static int Tick(byte b_tick) {
        m_bLastTimeTick = b_tick;

        if (m_bJumpEnable == false) {
            if (m_nSpeedUp > GameWorld.c_nGravityPerTick) {
                m_nSpeedUp = FP.sub(m_nSpeedUp, GameWorld.c_nGravityPerTick);
                //#if !IMGGROUP_12x12 && !IMGGROUP_12x12xLimited
                    if ((FP.toInt(m_nSpeedUp) & 1) == 0) m_nSpeedUp = FP.add(m_nSpeedUp, FP.toFP(1));
                    else m_nSpeedUp = FP.sub(m_nSpeedUp, FP.toFP(1));
                //#endif
            }
            else {
                m_nSpeedUp = 0;
                m_nSpeedDown = FP.add(m_nSpeedDown, GameWorld.c_nGravityPerTick << 1);
            }
        }

        if (m_nPickAxe > 0) {
            if ((m_nPickAxe & 1) == 0) {
                if (m_blDirRight)
                    animItemPickAxeRight.Tick();
                else
                    animItemPickAxeleft.Tick();
            }
            m_nPickAxe--;
        }

        // animation tick
        animationCurrent.Tick();

        // Process end of different animations
        if ((animationCurrent.nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0) {
            if (m_nCurAnimID == c_nAnimID_TeleportIn && isCurrentObject(objTeleportNextIndex, ObjID.nObjID_Teleport)) {
                m_nPosX = GameWorld.dynamicObjects[objTeleportNextIndex].m_nPosX;
                m_nPosY = GameWorld.dynamicObjects[objTeleportNextIndex].m_nPosY - 2;
                m_nTmpPosX = m_nPosX;
                m_nTmpPosY = m_nPosY;

                //#if BACK_BUFFER_FULL || BACK_BUFFER_LEVEL
                    GameWorld.nWndCX = Hero.m_nPosX;
                    GameWorld.nWndCY = Hero.m_nPosY;
                    GameWorld.prepareBackBuffer();
                //#endif

                setAnim(c_nAnimID_TeleportOut);
            }
            else if(m_nCurAnimID == c_nAnimID_TeleportOut) {
                m_nKeybMode = nModeNormal;
                ForceStop();
            }
            //#if !IMGGROUP_12x12xLimited
                else if (m_nCurAnimID == c_nAnimID_Turn) {
                    setAnim(c_nAnimID_Go);
                }
                else if (m_nCurAnimID == c_nAnimID_CannonCharging) {
                    animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                }
                else if ((m_nCurAnimID == c_nAnimID_DropDeath) || (m_nCurAnimID == c_nAnimID_FireDeath) || (m_nCurAnimID == c_nAnimID_TODeath)) {
                    animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                    animationCurrent.SetLastFrame();
                }
            //#endif
            else if (m_nCurAnimID == c_nAnimID_Death) {
                m_blVisible = false;
            }
        }

        // cannon help
        if (isCurrentObject(objCurrentIndex, ObjID.nObjID_Cannon) && (cannonShowTime == 0)) {
            cannonWaitTime++;
            if (cannonWaitTime > c_nMessWaitTime) {
                cannonWaitTime = 0;
                cannonShowTime = c_nMessShowTime;
                GameMenu.strToText(cannonMessQueue[cannonCurMess], false);
            }
        }
        else if (cannonWaitTime != 0) {
            cannonWaitTime = 0;
        }

        // NORMAL MODE
        if (m_nKeybMode == nModeNormal) {
            // Marv falls to deep space
            if ((m_nPosY > GameWorld.gps_height) && (m_nDeathTicks == 0)) {
                m_nDeathTicks = 30;
                m_nImmortalTicks = 30;

                m_nSpeedRight = m_nSpeedLeft = m_nSpeed45Degree = 0;
                m_bJumpEnable = false;
                m_bJumper = 0;

                m_nLives--;

                //#if SOUND_MMAPI || SOUND_NOKIA_RT || SAMSUNG_MMF || SHARP_MMF
                    MTMCanvas.soundPlay(Constants.SOUND_DIE);
                //#endif
            }

            if ((m_bTransporter == false) && (m_bCrashingPlatform == false)) objCurrentIndex = -1;
            else {
                // Marv stay on Transporter
                if (m_bTransporter == true) {
                    if (GameWorld.dynamicObjects[objCurrentIndex].objState != Constants.TRANSPORTER_STATE_WAIT) {
                        m_nPosX += GameWorld.dynamicObjects[objCurrentIndex].objStepX;
                        m_nPosY += GameWorld.dynamicObjects[objCurrentIndex].objStepY;
                    }
                    else {
                        m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].objPosY;
                    }
                }

                // Marv stay on Crashing platform
                if (m_bCrashingPlatform == true) {
                    if (GameWorld.dynamicObjects[objCurrentIndex].objState == Constants.CRASHING_PLATFORM_STATE_FALL) {
                        m_nPosY += GameWorld.dynamicObjects[objCurrentIndex].objStepY / Constants.CRASHING_PLATFORM_STEP_DIV;

                        if (m_nPosY-animationCurrent.GetCurFrmHeight() > GameWorld.gps_height) {
                            m_blVisible = false;

                            GameWorld.dynamicObjects[objCurrentIndex].objStepY = -Constants.TRANSPORTER_STEP_Y;
                            GameWorld.dynamicObjects[objCurrentIndex].objState = Constants.CRASHING_PLATFORM_STATE_CLIMB;
                            GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.Tick();

                            GameWorld.dynamicObjects[objCurrentIndex].m_blActive = false;
                        }
                    }
                    else if (!GameWorld.dynamicObjects[objCurrentIndex].m_blActive) {
                        if (GameWorld.dynamicObjects[objCurrentIndex].objState == Constants.CRASHING_PLATFORM_STATE_SLOW_DOWN) {
                            m_nPosY += GameWorld.dynamicObjects[objCurrentIndex].objStepY / Constants.CRASHING_PLATFORM_STEP_DIV;
                        }
                        else  if (GameWorld.dynamicObjects[objCurrentIndex].objState == Constants.CRASHING_PLATFORM_STATE_CLIMB) {
                            m_nPosY += GameWorld.dynamicObjects[objCurrentIndex].objStepY;
                        }
                    }
                    else {
                        m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].objPosY;
                    }   
                }
            }

            // Marv falls after contacting with some LevObjs (Cannon, Crashing pl., Transporter)
            if (m_nFlightDir != Constants.DIRECTION_FLY_NONE) {
                if ((m_nFlightDir & Constants.DIRECTION_FLY_LEFT) != 0) {
                    m_nSpeedLeft = FP.toInt(m_nSpeed45Degree);
                    m_nSpeedRight = 0;
                }
                else if((m_nFlightDir & Constants.DIRECTION_FLY_RIGHT) != 0) {
                    m_nSpeedLeft = 0;
                    m_nSpeedRight = FP.toInt(m_nSpeed45Degree);
                }

                if ((m_nFlightDir & Constants.DIRECTION_FLY_UP) != 0) {
                    m_nSpeedUp += m_nSpeed45Degree >> 1;
                    m_nFlightDir &= ~Constants.DIRECTION_FLY_UP;
                }
                else if((m_nFlightDir & Constants.DIRECTION_FLY_DOWN) != 0 ) {
                    m_nSpeedUp -= m_nSpeed45Degree >> 1;
                    m_nFlightDir &= ~Constants.DIRECTION_FLY_DOWN;
                }

                if (m_nSpeed45Degree > 0) {
                    m_nSpeed45Degree -= FP.div(1, 5);
                }
                else {
                    m_nFlightDir = Constants.DIRECTION_FLY_NONE;
                }
            }
         
            Move();
        }
        // CANNON MODE
        else if(m_nKeybMode == nModeCannon) {
            //#if !IMGGROUP_12x12xLimited
                if (m_nCurAnimID == c_nAnimID_TODeath)
            //#else
                if (m_nCurAnimID == c_nAnimID_Death)
            //#endif
           {
                // same as "climb out from cannon"
                GameWorld.dynamicObjects[objCurrentIndex].m_nParam = 0;
                GameWorld.dynamicObjects[objCurrentIndex].animationCurrent = GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON];
                GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.Reset();
                GameWorld.dynamicObjects[objCurrentIndex].m_blActive = false;
            }

            int phase = GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8;
            int pow = GameWorld.dynamicObjects[objCurrentIndex].m_nParam & 0xff;
            if (phase == LevObj.c_bCannonState_ClimbIn) { // climb in to cannon
                if((GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0)
                {
                    GameWorld.dynamicObjects[objCurrentIndex].m_nParam = (short)((LevObj.c_bCannonState_Move << 8) | pow);
                }
            }
            else if(phase == LevObj.c_bCannonState_ClimbOut) { // climb out from cannon
                if ((GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0) {
                    GameWorld.dynamicObjects[objCurrentIndex].m_nParam = 0;
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent = GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON];
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.Reset();
                    GameWorld.dynamicObjects[objCurrentIndex].m_blActive = false;

                    m_nKeybMode = nModeNormal;
                    m_blVisible = true;

                    setCannonMessQueue(LevObj.c_bCannonState_Charging, true);
                }
            }
            else if(phase == LevObj.c_bCannonState_Fire) { // cannon's fire was ended
                if ((GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON_FIRE].nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0) {
                    // define amount of tiles
                    int nTiles = pow * 2 + 2;

                    // settings of direction of flight
                    int hw = GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.GetCurFrmWidth() >> 1;
                    switch (GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nCurFrame) {
                        case 1:
                            GameWorld.dynamicObjects[objCurrentIndex].objState = Constants.DIRECTION_FLY_LEFT;
                            m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX - hw;
                            nTiles = nTiles * 10 / 14;
                            if(m_blDirRight) m_blDirRight = false;
                        break;
                        case 3:
                            GameWorld.dynamicObjects[objCurrentIndex].objState = Constants.DIRECTION_FLY_RIGHT;
                            m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX + hw;
                            nTiles = nTiles * 10 / 14;
                            if(!m_blDirRight) m_blDirRight = true;
                        break;
                        case 0:
                        case 2:
                            GameWorld.dynamicObjects[objCurrentIndex].objState = Constants.DIRECTION_FLY_NONE;
                            m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                        break;
                    }

                    // calculating of start speed of flight
                    //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                        long d = - FP.sub(GameWorld.c_nGravityPerTick, FP.div(1, 5));
                    //#else
                        long d = - GameWorld.c_nGravityPerTick;
                    //#endif
                        long distance = FP.toFP((nTiles+2)*TileDrawer.nTileWidth);

                        long number = d*d - ((distance*d) << 3);

                        //sqrt(number)
                        long result = 0; 
                        long div = number; 

                        if (number > 0) {
                            do {
                                result = div;
                                div = (number / div + div) >> 1; 
                            }
                            while (result > div);
                        }
                        m_nSpeedUp = (d + result) >> 1;
                        m_nSpeedDown = 0;

                        // horizontal speed
                        switch (GameWorld.dynamicObjects[objCurrentIndex].objState) {
                            case Constants.DIRECTION_FLY_LEFT:
                            case Constants.DIRECTION_FLY_RIGHT:
                                m_nSpeed45Degree = FP.toInt(distance / (1 - m_nSpeedUp/d));
                            break;
                            case Constants.DIRECTION_FLY_NONE:
                                m_nSpeed45Degree = 0;
                            break;
                        }

                        // common settings
                        setAnim(c_nAnimID_CannonFlying);
                        m_nPosY -= GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.GetCurFrmHeight();

                        GameWorld.dynamicObjects[objCurrentIndex].m_nParam = 1;
                        GameWorld.dynamicObjects[objCurrentIndex].m_blActive = false;
                        // save objCurrentIndex to objTeleportNextIndex
                        objTeleportNextIndex = objCurrentIndex;

                        m_nFlightDir = GameWorld.dynamicObjects[objCurrentIndex].objState;
                        objCurrentIndex = -1;

                        m_bJumpEnable = false;
                        m_nKeybMode = nModeCannonFlying;

                        m_blVisible = true;

                        setCannonMessQueue(LevObj.c_bCannonState_Charging, true);
                }
            }
        }
        else if(m_nKeybMode == nModeCannonFlying) {
            switch (m_nFlightDir) {
                case Constants.DIRECTION_FLY_LEFT:
                    m_nSpeedLeft = m_nSpeed45Degree;
                    m_nSpeedRight = 0;
                break;
      
                case Constants.DIRECTION_FLY_RIGHT:
                    m_nSpeedLeft = 0;
                    m_nSpeedRight = m_nSpeed45Degree;
                break;
            }

            if (m_nSpeedUp <= 0) {
                // objTeleportNextIndex as objCurrentIndex
                GameWorld.dynamicObjects[objTeleportNextIndex].animationCurrent = GameWorld.dynamicObjects[objTeleportNextIndex].animationList[Constants.ANIMATION_CANNON];
                GameWorld.dynamicObjects[objTeleportNextIndex].animationCurrent.Reset();
                objTeleportNextIndex = -1;

                m_nKeybMode = nModeNormal;
                m_nSpeed45Degree = (int) FP.toFP(m_nSpeed45Degree);
            }

            Move();
        }
        // LADDER MODE
        else if (m_nKeybMode == nModeLadder) {
            if (m_nDeathTicks == 0) {
                if (m_bJumpEnable == false) m_bJumpEnable = true;
                if (m_nFlightDir != Constants.DIRECTION_FLY_NONE) m_nFlightDir = Constants.DIRECTION_FLY_NONE;

                m_nPosY += SPEED_VMOVE * m_VDirection;

                if ((m_VDirection == DIRECTION_MOVE_DOWN) && (m_nPosY > GameWorld.dynamicObjects[objCurrentIndex].m_nParam - 1)) {
                    m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].m_nParam - 1;
                    m_VDirection = DIRECTION_MOVE_NONE;
                              
                    m_nKeybMode = nModeNormal;
                    m_nSpeedUp = 0;
                    m_nSpeedDown = GameWorld.c_nGravityPerTick;
                    m_bJumpEnable = true;

                    ForceStop();
                }
            }
            //#if !IMGGROUP_12x12xLimited
                else if ((m_nCurAnimID == c_nAnimID_TODeath) && (animationCurrent.nCurFrame == 2)) {
                    m_nKeybMode = nModeNormal;
                    m_nSpeedDown = GameWorld.c_nGravityPerTick;
                }
            //#endif
        }
        else  if(m_nKeybMode == nModeLadderFinish) {
            if (m_VDirection == DIRECTION_MOVE_UP) {
                m_nKeybMode = nModeLadderStart;
                setAnim(c_nAnimID_LadderStartFinish);
            }
            else if(m_VDirection == DIRECTION_MOVE_DOWN) {
                int lh = PicDrawer.GetPicHeight(PicID.nPicID_ladder_tile_full); // Calculate the top of ladder

                GameWorld.shiftYPos = -lh;
                GameWorld.shiftYInd = 0;
                m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].m_nPosY + lh;

                m_nKeybMode = nModeLadder;
            }
        }
        else if(m_nKeybMode == nModeLadderStart) {
            if (m_VDirection == DIRECTION_MOVE_UP) {
                m_VDirection = DIRECTION_MOVE_NONE;
                m_nKeybMode = nModeNormal;
                ForceStop();
            }
            else if(m_VDirection == DIRECTION_MOVE_DOWN) {
                m_nKeybMode = nModeLadderFinish;
                setAnim(c_nAnimID_LadderStartFinish);
            }
        }
        // SLIDE MODE
        else if(m_nKeybMode == nModeSlide) {
            int lh = PicDrawer.GetPicHeight(PicID.nPicID_marv_f1);
            int th = PicDrawer.GetPicHeight(PicID.nPicID_slide_t);

            //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 1;
                int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 1;
            //#elif IMGGROUP_18x18
                int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 1;
                int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 2;
            //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 2;
                int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 3;
            //#elif IMGGROUP_36x36
                int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 3;
                int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 4;
            //#endif

            // Y-axis moving
            if ((m_nPosY - lh) < (GameWorld.dynamicObjects[objCurrentIndex].m_nParam + th)) {
                m_nPosY += Constants.SLIDE_SPEED;

                if (m_nPosY > (GameWorld.dynamicObjects[objCurrentIndex].m_nParam + th + lh)) {
                    m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].m_nParam + th + lh;
                }

                // X-axis moving
                if (((m_nPosY - lh) > GameWorld.dynamicObjects[objCurrentIndex].m_nPosY) && ((m_nPosY - lh) < GameWorld.dynamicObjects[objCurrentIndex].m_nParam)) {
                    // to left
                    if (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam < GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                        m_nPosX -= Constants.SLIDE_SPEED;

                        if (m_nPosX < (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam - hw + neck)) {
                            m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam - hw + neck;
                        }
                    }
                    // to right
                    else if (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam > GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                        m_nPosX += Constants.SLIDE_SPEED;

                        if (m_nPosX > (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam + hw - neck)) {
                            m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam + hw - neck;
                        }
                    }
                }
            }
            // end of slide
            else {
                if (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam < GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                    m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam - hw + neck;
                }
                else if (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam > GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                    m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam + hw - neck;
                }
                else {
                    m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam;
                }

                m_bJumpEnable = false;
                m_nSpeedUp = 0;
                m_nSpeedDown = GameWorld.c_nGravityPerTick;

                m_blVisible = true;
                m_nKeybMode = nModeNormal;
            }
        }

        if ( m_nDeathTicks > 1 ) {
            --m_nDeathTicks;
            if (m_nDeathTicks == 1) return c_nRetHeroDeath;
        }
        else if (m_nImmortalTicks > 0) {
            boolean flag = false;

            if (((m_nKeybMode == nModeCannon) && ((GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8) != LevObj.c_bCannonState_Charging)) || ((m_nKeybMode == nModeSlide) || (m_nKeybMode == nModeTeleport))) {
                flag = true;
            }

            if (!flag) {
                if ((m_nImmortalTicks & 1) == 0) {
                    m_blVisible = !m_blVisible;
                }

                if (m_nImmortalTicks == 1) {
                    m_blVisible = true;
                }
            }

            m_nImmortalTicks--;
        }
        return c_nRetNone;
    }

    /**
     *
     */
    public static boolean isCurrentObject(int objIndex, int objTyoe) {
        return (objIndex >  -1) && (objIndex < GameWorld.dynamicObjects.length) && (GameWorld.dynamicObjects[objIndex].nClassID == objTyoe);
    }
   
    /**
     *
     */
    public static void monsterKilled(byte type) {
        if (m_blDynamite) m_blDynamite = false;

        switch (type) {
            case Constants.TYPE_MORTALFLY:
                m_nTotalScores += Constants.SCORE_MORTALFLY;
            break;

            case Constants.TYPE_JUMPINGBEAST:
                m_nTotalScores += Constants.SCORE_JUMPINGBEAST;
            break;

            case Constants.TYPE_SLIME:
                m_nTotalScores += Constants.SCORE_SLIME;
            break;
        }

        //#if SOUND_MMAPI || SOUND_NOKIA_RT || SAMSUNG_MMF || SHARP_MMF
            MTMCanvas.soundPlay(Constants.SOUND_KILL);
        //#endif
    }
   
    /**
     *
     */
    public static int OnLevObjCollis(int objIndex, boolean bl_vert, boolean bl_right, boolean bl_down) {
        if (((m_nKeybMode == nModeNormal) || (m_nKeybMode == nModeCannonFlying)) && ((objCurrentIndex == -1) || isCurrentObject(objCurrentIndex, ObjID.nObjID_Ladder))) {
            switch (GameWorld.dynamicObjects[objIndex].nClassID) {
                case ObjID.nObjID_Firewall: {
                    boolean flag = false;

                    if (m_nSpeedUp == 0) {
                        if ((m_nSpeedDown == GameWorld.c_nGravityPerTick) && ((GameWorld.dynamicObjects[objIndex].m_nPosY - m_nPosY) < 3)) {
                            flag = true;
                        }
                        else if (m_nSpeedDown > GameWorld.c_nGravityPerTick) {
                            flag = true;
                        }
                    }
                    if (flag && GameWorld.dynamicObjects[objIndex].m_blActive) {
                        //#if !IMGGROUP_12x12xLimited
                            ForceDeath( c_nAnimID_FireDeath );
                        //#else
                            ForceDeath( c_nAnimID_Death );
                        //#endif
                        m_nPosY = GameWorld.dynamicObjects[objIndex].m_nPosY;
                        m_nTmpPosY = m_nPosY;
                        return COLLIS_RET_STOP;
                    }
                    break;
                }

                case ObjID.nObjID_Bonus: {
                    if (GameWorld.dynamicObjects[objIndex].m_blActive) {
                        if (GameWorld.dynamicObjects[objIndex].m_nParam == LevObj.c_shBonusDynamite) {
                            if (( m_blDynamite == false ) && (m_nPickAxe == 0)) {
                                m_blDynamite = true;
                                GameWorld.dynamicObjects[objIndex].m_blActive = false;
                            }
                        }

                        if (GameWorld.dynamicObjects[objIndex].m_nParam == LevObj.c_shBonusPickAxe) {
                            if ( m_blDynamite == false ) {
                                m_nPickAxe += c_nPickAxeTime;
                                GameWorld.dynamicObjects[objIndex].m_blActive = false;
                            }
                        }

                        if (GameWorld.dynamicObjects[objIndex].m_nParam == LevObj.c_shBonusXLife) {
                            if (m_nLives < c_nMaxLives) {
                                m_nLives++;
                            }
                            GameWorld.dynamicObjects[objIndex].m_blActive = false;
                        }

                        if (GameWorld.dynamicObjects[objIndex].m_nParam > 0) {
                            GameWorld.dynamicObjects[objIndex].m_blActive = false;
                            m_nTotalScores += GameWorld.dynamicObjects[objIndex].m_nParam;
                            //#if SOUND_MMAPI || SOUND_NOKIA_RT || SAMSUNG_MMF || SHARP_MMF
                                MTMCanvas.soundPlay(Constants.SOUND_BONUS);
                            //#endif
                        }
                    }
                    break;
                }

                case ObjID.nObjID_Spring: {
                    if ((m_nDeathTicks == 0) && bl_down) {
                        GameWorld.dynamicObjects[objIndex].animationCurrent.Tick();
                        m_nPosY = GameWorld.dynamicObjects[objIndex].m_nPosY - GameWorld.dynamicObjects[objIndex].animationCurrent.GetCurFrmHeight();
                        m_nTmpPosY = m_nPosY;
                        m_bJumper = 1;

                        if ((GameWorld.dynamicObjects[objIndex].animationCurrent.nStateFlg & Animation.cnANIM_STATE_END_OF_CYCLE) != 0) {
                            if (m_nCurAnimID == c_nAnimID_Fall) {
                                m_nTotalDropHeight = 0;
                            }

                            // !!! Is is important to set animation befor other operations
                            m_blChangeAnimEnable = true;
                            setAnim( c_nAnimID_Jump );
                            animationCurrent.SetFrame( 0 );

                            m_bJumpEnable = true;
                            m_nFlightDir = Constants.DIRECTION_FLY_NONE;

                            ForceMoveJump( false, false );
                            m_nTotalDropHeight += TileDrawer.nTileWidth << 1; // neutral m_nTotalDropHeight after ForceMoveJump()

                            if (MTMCanvas.keyIsHeld(Constants.keyUP | Constants.keyNUM2)) {
                                //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited || IMGGROUP_18x18
                                    m_nSpeedUp += FP.toFP(m_nTotalDropHeight / 9);
                                //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                                    m_nSpeedUp += FP.toFP(m_nTotalDropHeight / 11);
                                //#elif IMGGROUP_36x36
                                    m_nSpeedUp += FP.toFP(m_nTotalDropHeight / 10);
                                //#endif
                            }
                            else {
                                //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited || IMGGROUP_18x18
                                    m_nSpeedUp += FP.toFP((m_nTotalDropHeight / 9) - 3);
                                //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                                    m_nSpeedUp += FP.toFP((m_nTotalDropHeight / 11) - 4);
                                //#elif IMGGROUP_36x36
                                    m_nSpeedUp += FP.toFP((m_nTotalDropHeight / 10) - 6);
                                //#endif
                                if (FP.toInt(m_nSpeedUp) < c_nSpeedJump) {
                                    m_nSpeedUp = FP.toFP(c_nSpeedJump);
                                }
                            }
                            m_nTotalDropHeight = 0;
                            GameWorld.dynamicObjects[objIndex].animationCurrent.Reset();
                        }
                        return COLLIS_RET_NO_MOVING;
                    }
                    break;
                }

                case ObjID.nObjID_Slide:
                    m_blVisible = false;
                    m_nKeybMode = nModeSlide;
                    m_nPosX = GameWorld.dynamicObjects[objIndex].m_nPosX;
                    m_nPosY = GameWorld.dynamicObjects[objIndex].m_nPosY;
                    m_nSpeedLeft = m_nSpeedRight = 0;
                    // continue in next case

                case ObjID.nObjID_Cannon:
                case ObjID.nObjID_Ladder:
                case ObjID.nObjID_Teleport:
                    objCurrentIndex = objIndex;
                break;

                case ObjID.nObjID_CrashingPlatform:
                    if ((m_bCrashingPlatform == false) && (m_nSpeedUp == 0)) {
                        objCurrentIndex = objIndex;

                        m_bCrashingPlatform = true;
                        m_bJumpEnable = true;
                        m_nFlightDir = Constants.DIRECTION_FLY_NONE;
                        m_nSpeedDown = 0;

                        if ((GameWorld.dynamicObjects[objCurrentIndex].objState != Constants.CRASHING_PLATFORM_STATE_CLIMB) && (GameWorld.dynamicObjects[objCurrentIndex].objState != Constants.CRASHING_PLATFORM_STATE_WAIT)) {
                            m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].objPosY + GameWorld.dynamicObjects[objCurrentIndex].objStepY / Constants.CRASHING_PLATFORM_STEP_DIV;
                        }
                        else {
                            m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].objPosY;
                        }
                        GameWorld.dynamicObjects[objCurrentIndex].objState = Constants.CRASHING_PLATFORM_STATE_MARV_STEP;
                        return COLLIS_RET_NO_MOVING;
                    }
                break;

                case ObjID.nObjID_TransporterHorz:
                case ObjID.nObjID_TransporterVert:
                case ObjID.nObjID_Transporter45Degree:
                    if ((m_bTransporter == false) && (m_nSpeedUp == 0)) {
                        objCurrentIndex = objIndex;

                        m_bTransporter = true;
                        m_bJumpEnable = true;
                        m_nFlightDir = Constants.DIRECTION_FLY_NONE;
                        m_nSpeedDown = 0;

                        if (GameWorld.dynamicObjects[objCurrentIndex].objState != Constants.TRANSPORTER_STATE_WAIT) {
                            m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].objPosY + GameWorld.dynamicObjects[objCurrentIndex].objStepY;
                        }
                        else {
                            m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].objPosY;
                        }
                        return COLLIS_RET_NO_MOVING;
                    }
                break;
            }
        }
        return COLLIS_RET_NONE;
    }

    /**
     *
     */
    private static boolean IsCanMove(boolean bl_vert, boolean bl_right, boolean bl_down, boolean bl_paint) {
        //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
            int hw = 3; // 4 - 1 <= needs in decrease
        //#elif IMGGROUP_18x18
            int hw = 5; // 6
        //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
            int hw = 8;
        //#elif IMGGROUP_36x36
            int hw = 12;
        //#endif
        int h = animationCurrent.GetCurFrmHeight();

        int n_left = m_nTmpPosX - hw;
        int n_top = m_nTmpPosY - h;
        int n_right = m_nTmpPosX + hw;

        boolean bl_res = false;

        // tile-matrix
        int res = GameWorld.IsIntersect(n_left, n_top, n_right, m_nTmpPosY, bl_vert, bl_right, bl_down, bl_paint);
        if (res != GameWorld.nRet_CantMove) {
            if (res != 0) {
                m_nTmpPosY += res;
                m_nPosY = m_nTmpPosY;
            }
            bl_res = (res <= 0);
        }

        // dynamic objects
        int n_dyn_res = GameWorld.IsIntersectLevObj(n_left, n_top, n_right, m_nTmpPosY, bl_vert, bl_right, bl_down);
        if (n_dyn_res == COLLIS_RET_NO_MOVING) {
            bl_res = false;
        }
        if ( n_dyn_res == COLLIS_RET_STOP ) {
            bl_res = false;
        }
        return bl_res;
    }

    /**
     *
     */
    private static void Move() {
        // Marv's moving logic
        // collision detection do in order - first x-direction (for help to hero)
        // second y-direction.

        if ((m_nSpeedLeft > 0) || (m_nSpeedRight > 0) || (m_nSpeedUp > 0) || (m_nSpeedDown > 0)) {
            // moving for X, Y
            int n_lx = (m_nSpeedRight - m_nSpeedLeft);
            int n_dx = 0;
            if (n_lx != 0) {
                n_dx = (n_lx > 0) ? 1 : -1;
            }
            int n_ly = FP.toInt( FP.sub(m_nSpeedDown, m_nSpeedUp ));
            int n_dy = 0;
            if (n_ly != 0) {
                n_dy = (n_ly > 0) ? 1 : -1;
            }

            n_lx = (n_lx > 0) ? n_lx : -n_lx;
            n_ly = (n_ly > 0) ? n_ly : -n_ly;
            int n_cnt = (n_lx > n_ly) ? n_lx : n_ly;

            m_nTmpPosX = m_nPosX;
            m_nTmpPosY = m_nPosY;
            boolean b_do_x = (n_dx != 0);
            boolean b_do_y = (n_dy != 0);
            boolean bl_drop = false;
            boolean bl_paint = (n_dy > 0) && (m_nDeathTicks == 0) && (m_nTotalDropHeight < c_nDeadHeight);
            boolean bl_right = (n_dx > 0);
            boolean bl_down = (n_dy > 0);

            for (int i = 0; (b_do_x || b_do_y) && ( i < n_cnt ); i++) {
                if (b_do_x) {
                    m_nTmpPosX += n_dx;

                    n_lx -= 1;
                    b_do_x = (n_lx > 0);

                    if (IsCanMove(false, bl_right, false, false)) {
                        m_nPosX = m_nTmpPosX;
                    }
                    else {
                        m_nTmpPosX = m_nPosX;
                        b_do_x = false;
                    }
                }

                if (b_do_y) {
                    m_nTmpPosY += n_dy;

                    n_ly -= 1;
                    b_do_y = (n_ly > 0);

                    if (IsCanMove(true, false, bl_down, bl_paint)) {
                        // in the air
                        if ((m_bJumpEnable == true) && (m_bTransporter == false)) m_bJumpEnable = false;

                        bl_drop = ( n_dy > 0 );
                        if ( bl_drop ) {
                            m_nTotalDropHeight += n_dy;
                        }

                        m_nPosY = m_nTmpPosY;

                        if ((m_nTotalDropHeight > c_nDeadHeight) && (m_bJumper == 0) && (m_nDeathTicks == 0)) {
                            m_blChangeAnimEnable = true;
                            setAnim(c_nAnimID_Fall);
                        }
                    }
                    else // in ground
                    {
                        if (m_bJumper == 0) {
                            if (m_bJumpEnable == false) {
                                m_nSpeedDown = GameWorld.c_nGravityPerTick;
                                m_nSpeedUp = 0;

                                if ((n_dy > 0) && !MTMCanvas.keyIsHeld(Constants.keyLEFT | Constants.keyNUM4 | Constants.keyRIGHT | Constants.keyNUM6 )) {
                                    b_do_x = false;
                                }
                            }

                            if (n_dy > 0) {
                                bl_drop = false;
                                m_bJumpEnable = true;
                                m_nFlightDir = Constants.DIRECTION_FLY_NONE;

                                if (m_nCurAnimID == c_nAnimID_Jump) {
                                    m_blChangeAnimEnable = true;
                                    setAnim( c_nAnimID_Go );
                                }
                                else if (m_nCurAnimID == c_nAnimID_Fall) {
                                    //#if !IMGGROUP_12x12xLimited
                                        ForceDeath( c_nAnimID_DropDeath );
                                    //#else
                                        ForceDeath( c_nAnimID_Death );
                                    //#endif
                                }
                                m_nTotalDropHeight = 0;
                            }
                        }
                        else {
                            m_bJumper--;
                        }
                        b_do_y = false;
                        m_nTmpPosY = m_nPosY;
                    }
                }
            }

            if (bl_drop && (m_nTotalDropHeight > 6) && (m_bJumper == 0) && (m_nDeathTicks == 0)) {
                if ( m_nCurAnimID != c_nAnimID_Fall ) {
                    m_blChangeAnimEnable = true;
                    setAnim(c_nAnimID_Jump);
                    animationCurrent.SetFrame( 1 );
                }
            }
        }
    }

    /*
     *
     */
    public static void ForceDeath( int c_nAnimID) {
        if (m_nDeathTicks == 0) {
            m_blChangeAnimEnable = true;
            setAnim(c_nAnimID);
            m_blChangeAnimEnable = false;

            //#if !IMGGROUP_12x12xLimited
                if (m_nCurAnimID != c_nAnimID_TODeath) {
                    m_blVisible = true;
                }
            //#endif

            m_nDeathTicks = 30;
            m_nImmortalTicks = 30;

            m_nSpeedUp = m_nSpeedDown = 0;
            m_nSpeedRight = m_nSpeedLeft = 0;
            m_bJumper = 0;

            m_nLives--;

            //#if SOUND_MMAPI || SOUND_NOKIA_RT || SAMSUNG_MMF || SHARP_MMF
                MTMCanvas.soundPlay(Constants.SOUND_DIE);
            //#endif
        }
    }

    /*
     *
     */
    public static void ForceStop() {
        if (m_nKeybMode == nModeNormal) {
            m_nSpeedLeft = m_nSpeedRight = 0;

            if ((m_bJumpEnable) && (m_nDeathTicks == 0)) {
                setAnim(c_nAnimID_Idle);
            }
        }
        else if (m_nKeybMode == nModeLadder) {
            m_VDirection = DIRECTION_MOVE_NONE;
            setAnim(c_nAnimID_LadderPaused);
        }
    }

    /*
     *
     */
    public static void ForceMoveLeft() {
        if (m_nKeybMode == nModeNormal) {
            //#if !IMGGROUP_12x12xLimited
                if((m_nDeathTicks == 0) && (m_nCurAnimID != c_nAnimID_Turn) && (m_nCurAnimID != c_nAnimID_Fall))
            //#else
                if((m_nDeathTicks == 0) && (m_nCurAnimID != c_nAnimID_Fall))
            //#endif
            {
                if (m_nFlightDir != Constants.DIRECTION_FLY_NONE) m_nFlightDir = Constants.DIRECTION_FLY_NONE;

                if (m_bJumpEnable) {
                    m_nSpeedLeft = SPEED_HMOVE;
                    m_nSpeedRight = 0;
                    if (m_blDirRight) {
                        m_blDirRight = false;
                        //#if !IMGGROUP_12x12xLimited
                            setAnim(c_nAnimID_Turn);
                        //#else
                            m_nCurAnimID = c_nAnimID_Idle;
                            setAnim(c_nAnimID_Go);
                        //#endif
                    }
                    else {
                        setAnim(c_nAnimID_Go);
                    }
                }
                else if ( m_nCurAnimID == c_nAnimID_Jump ) {
                    if (m_blDirRight) {
                        if ( m_nSpeedRight > 0 ) m_nSpeedRight--;
                        if ( m_nSpeedRight == 0 ) {
                            m_nSpeedLeft = SPEED_HMOVE >> 1;

                            m_blDirRight = false;
                            m_nCurAnimID = c_nAnimID_None;
                            setAnim( c_nAnimID_Jump );
                        }
                    }
                    else {
                        m_nSpeedLeft = SPEED_HMOVE + (SPEED_HMOVE >> 1);
                    }
                }
            }
        }
        else if (m_nKeybMode == nModeCannon) {
            int phase = GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8;
                if (phase == LevObj.c_bCannonState_Move) {
                    m_nTmpPosY = GameWorld.dynamicObjects[objCurrentIndex].m_nPosY;
                    if (IsCanMove(false, false, false, false)) {
                        // !!! It is important to increase "m_nTmpPosY"
                        m_nTmpPosY++;
                        m_nPosX -= SPEED_HMOVE;
                        GameWorld.dynamicObjects[objCurrentIndex].m_nPosX -= SPEED_HMOVE;
                        m_nTmpPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX - (GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.GetCurFrmWidth() >> 1);

                        if (IsCanMove(true, false, true, true)) {
                            m_nPosX += SPEED_HMOVE;
                            GameWorld.dynamicObjects[objCurrentIndex].m_nPosX += SPEED_HMOVE;
                        }
                    }
                    cannonCurMess = 0;
                    cannonWaitTime = 0;
                    cannonShowTime = 0;
                }
        }
        else if (m_nKeybMode == nModeLadder) {
            m_nSpeedUp = 0;
            m_nSpeedDown = GameWorld.c_nGravityPerTick;

            m_bJumpEnable = true;
            m_nFlightDir = Constants.DIRECTION_FLY_NONE;

            m_VDirection = DIRECTION_MOVE_NONE;

            m_nKeybMode = nModeNormal;
            ForceMoveLeft();
        }
    }

    /*
     *
     */
    public static void ForceMoveRight() {
        if (m_nKeybMode == nModeNormal) {
            //#if !IMGGROUP_12x12xLimited
                if((m_nDeathTicks == 0) && (m_nCurAnimID != c_nAnimID_Turn) && (m_nCurAnimID != c_nAnimID_Fall))
            //#else
                if((m_nDeathTicks == 0) && (m_nCurAnimID != c_nAnimID_Fall))
            //#endif
            {
                if (m_nFlightDir != Constants.DIRECTION_FLY_NONE) m_nFlightDir = Constants.DIRECTION_FLY_NONE;

                if (m_bJumpEnable) {
                    m_nSpeedLeft = 0;
                    m_nSpeedRight = SPEED_HMOVE;

                    if (!m_blDirRight) {
                        m_blDirRight = true;
                        //#if !IMGGROUP_12x12xLimited
                            setAnim(c_nAnimID_Turn);
                        //#else
                            m_nCurAnimID = c_nAnimID_Idle;
                            setAnim(c_nAnimID_Go);
                        //#endif
                    }
                    else {
                        setAnim(c_nAnimID_Go);
                    }
                }
                else if (m_nCurAnimID == c_nAnimID_Jump) {
                    if (m_blDirRight) {
                        m_nSpeedRight = SPEED_HMOVE + (SPEED_HMOVE >> 1);
                    }
                    else {
                        if ( m_nSpeedLeft > 0 ) m_nSpeedLeft--;
                        if ( m_nSpeedLeft == 0 ) {
                            m_nSpeedRight = SPEED_HMOVE >> 1;

                            m_blDirRight = true;
                            m_nCurAnimID = c_nAnimID_None;
                            setAnim( c_nAnimID_Jump );
                        }
                    }
                }
            }
        }
        else if (m_nKeybMode == nModeCannon) {
            int phase = GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8;
            if (phase == LevObj.c_bCannonState_Move) {
                m_nTmpPosY = GameWorld.dynamicObjects[objCurrentIndex].m_nPosY;
                if (IsCanMove(false, true, false, false)) {
                    // !!! It is important to increase "m_nTmpPosY"
                    m_nTmpPosY++;
                    m_nPosX += SPEED_HMOVE;
                    GameWorld.dynamicObjects[objCurrentIndex].m_nPosX += SPEED_HMOVE;
                    m_nTmpPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX + (GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.GetCurFrmWidth() >> 1);

                    if (IsCanMove(true, false, true, true)) {
                        m_nPosX -= SPEED_HMOVE;
                        GameWorld.dynamicObjects[objCurrentIndex].m_nPosX -= SPEED_HMOVE;
                    }
                }

                cannonCurMess = 0;
                cannonWaitTime = 0;
                cannonShowTime = 0;
            }
        }
        else if(m_nKeybMode == nModeLadder) {
            m_nSpeedUp = 0;
            m_nSpeedDown = GameWorld.c_nGravityPerTick;

            m_bJumpEnable = true;
            m_nFlightDir = Constants.DIRECTION_FLY_NONE;

            m_VDirection = DIRECTION_MOVE_NONE;

            m_nKeybMode = nModeNormal;
            ForceMoveRight();
        }
    }

    /*
     *
     */
    public static void ForceMoveDown() {
        if (m_nKeybMode == nModeNormal) {
            if (m_nDeathTicks == 0) {
                if (isCurrentObject(objCurrentIndex, ObjID.nObjID_Ladder) && m_nPosY < GameWorld.dynamicObjects[objCurrentIndex].m_nParam - 1) {
                    m_nKeybMode = nModeLadder;
                    m_nTotalDropHeight = 0;
                    if (m_nPosX != GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                        GameWorld.shiftXPos = m_nPosX - GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                        GameWorld.shiftXInd = 0;
                        m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                    }
                    if (m_nPosY <= GameWorld.dynamicObjects[objCurrentIndex].m_nPosY) {
                        m_VDirection = DIRECTION_MOVE_DOWN;
                        m_nKeybMode = nModeLadderStart;
                    }
                    else {
                        setAnim(c_nAnimID_LadderMoving);
                    }
                }
                else {
                    ForceStop();
                }
            }
        }
        else if (m_nKeybMode == nModeCannon) {
            // climb out from cannon
            int phase = GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8;
            int pow = GameWorld.dynamicObjects[objCurrentIndex].m_nParam & 0xff;
            if (phase < LevObj.c_bCannonState_Fire) {
                GameWorld.dynamicObjects[objCurrentIndex].m_nParam = (short)((LevObj.c_bCannonState_ClimbOut << 8) | pow);
                GameWorld.dynamicObjects[objCurrentIndex].animationCurrent = GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON_CLIMB];

                if (phase > LevObj.c_bCannonState_Charging) {
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PLAY_REVERSED;
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.Reset();
                }
                else {
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nStateFlg |= Animation.cnANIM_STATE_END_OF_CYCLE;
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                }
            }
                cannonShowTime = -1;
        }
        else if(m_nKeybMode == nModeLadder) {
            m_VDirection = DIRECTION_MOVE_DOWN;
            setAnim(c_nAnimID_LadderMoving);
        }
    }

    /*
     *
     */
    public static void ForceMoveUp() {
        if (m_nKeybMode == nModeNormal) {
            if (m_nDeathTicks == 0) {
                if (isCurrentObject(objCurrentIndex, ObjID.nObjID_Ladder) && m_nPosY > GameWorld.dynamicObjects[objCurrentIndex].m_nPosY) {
                    m_nKeybMode = nModeLadder;
                    m_nTotalDropHeight = 0;
                    if (m_nPosX != GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                        GameWorld.shiftXPos = m_nPosX - GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                        GameWorld.shiftXInd = 0;
                        m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                    }
                    // correcting Marv's possition
                    int ach = animationCurrent.GetCurFrmHeight();
                    setAnim(c_nAnimID_LadderMoving);
                    m_nPosY -= FP.abs(ach - animationCurrent.GetCurFrmHeight());
                }
                else {
                    ForceMoveJump(false, false);
                }
            }
        }
        else if(m_nKeybMode == nModeCannon) {
            int phase = GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8;
            int pow = GameWorld.dynamicObjects[objCurrentIndex].m_nParam & 0xff;
            if ( phase == LevObj.c_bCannonState_Charging ) { // climb to cannon
                GameWorld.dynamicObjects[objCurrentIndex].m_nParam = (short)((LevObj.c_bCannonState_ClimbIn << 8) | pow);
                GameWorld.dynamicObjects[objCurrentIndex].animationCurrent = GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON_CLIMB];
                GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nStateFlg &= ~(Animation.cnANIM_STATE_PLAY_REVERSED | Animation.cnANIM_STATE_PAUSED );
                GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.Reset();
            }
            m_blVisible = false;

            setCannonMessQueue(LevObj.c_bCannonState_Move, true);
        }
        else if (m_nKeybMode == nModeLadder) {
            m_VDirection = DIRECTION_MOVE_UP;
            int lh = PicDrawer.GetPicHeight(PicID.nPicID_ladder_tile_full); // Calculate the top of ladder
            if (m_nPosY <= (GameWorld.dynamicObjects[objCurrentIndex].m_nPosY+lh)) {
                GameWorld.shiftYPos = m_nPosY - GameWorld.dynamicObjects[objCurrentIndex].m_nPosY + 2;
                GameWorld.shiftYInd = 0;
                m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].m_nPosY - 2;
                m_nKeybMode = nModeLadderFinish;
                        
                m_nSpeedUp = 0;
                m_nSpeedDown = GameWorld.c_nGravityPerTick;
                m_bJumpEnable = true;
            }
            else {
                setAnim(c_nAnimID_LadderMoving);
            }
        }
    }
   
    /*
     *
     */
    public static void ForceMoveJump(boolean bl_left, boolean bl_right) {
        if ( m_nKeybMode == nModeNormal ) {
            if ((m_nDeathTicks == 0) && (m_nCurAnimID != c_nAnimID_Fall)) {
                if (m_bJumpEnable) {
                    m_bJumpEnable = false; // sets to true when ground collis will detected
                    m_nSpeedUp = FP.toFP(c_nSpeedJump);
                    m_nSpeedDown = 0;
                    m_blChangeAnimEnable = true;

                    m_nTotalDropHeight -= TileDrawer.nTileWidth << 1; // same thing for falling to other platform with jump

                    if ( bl_left ) {
                        //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.div(1, 5));
                        //#elif IMGGROUP_18x18
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.div(2, 3));
                        //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.toFP(2));
                        //#else
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.toFP(4));
                        //#endif
                        m_nFlightDir = Constants.DIRECTION_FLY_LEFT;
                        m_blDirRight = false;
                    }

                    if ( bl_right ) {
                        //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.div(1, 5));
                        //#elif IMGGROUP_18x18
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.div(2, 3));
                        //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.toFP(2));
                        //#else
                            m_nSpeed45Degree = (int) FP.sub(FP.toFP(SPEED_HMOVE), FP.toFP(4));
                        //#endif
                        m_nFlightDir = Constants.DIRECTION_FLY_RIGHT;
                        m_blDirRight = true;
                    }
                    setAnim( c_nAnimID_Jump );
                }
                else { // on air
                    if (m_blDirRight ) {
                        if ( bl_left ) {
                            if (m_nSpeed45Degree > 0) {
                                m_nSpeed45Degree = 0;
                            }
                            else {
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE);
                                m_nFlightDir = Constants.DIRECTION_FLY_LEFT;

                                m_blDirRight = false;
                                m_nCurAnimID = c_nAnimID_None;
                                setAnim( c_nAnimID_Jump );
                            }
                        }
                        if ( bl_right ) {
                            //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + ((3 * SPEED_HMOVE) >> 2));
                            //#elif IMGGROUP_18x18
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + (SPEED_HMOVE >> 1));
                            //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + (SPEED_HMOVE >> 1));
                            //#else
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + (SPEED_HMOVE >> 1));
                            //#endif
                            m_nFlightDir = Constants.DIRECTION_FLY_RIGHT;
                        }
                    }
                    else {
                        if ( bl_left ) {
                            //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + ((3 * SPEED_HMOVE) >> 2));
                            //#elif IMGGROUP_18x18
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + (SPEED_HMOVE >> 1));
                            //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + (SPEED_HMOVE >> 1));
                            //#else
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE + (SPEED_HMOVE >> 1));
                            //#endif
                            m_nFlightDir = Constants.DIRECTION_FLY_LEFT;
                        }

                        if ( bl_right ) {
                            if (m_nSpeed45Degree > 0) {
                                m_nSpeed45Degree = 0;
                            }
                            else {
                                m_nSpeed45Degree = (int) FP.toFP(SPEED_HMOVE);
                                m_nFlightDir = Constants.DIRECTION_FLY_RIGHT;

                                m_blDirRight = true;
                                m_nCurAnimID = c_nAnimID_None;
                                setAnim( c_nAnimID_Jump );
                            }
                        }
                    }
                }
            }
        }
        else if(m_nKeybMode == nModeLadder) {
            m_VDirection = DIRECTION_MOVE_NONE;
            m_nKeybMode = nModeNormal;
            ForceMoveJump(bl_left, bl_right);
        }
    }

    /*
     *
     */
    public static void ForceFire() {
        if (m_nDeathTicks == 0) {
            if (isCurrentObject(objCurrentIndex, ObjID.nObjID_Teleport)) {
                objTeleportNextIndex = GameWorld.GetNextTeleport(GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8);
                if ((m_nCurAnimID != c_nAnimID_TeleportIn) && (m_nCurAnimID != c_nAnimID_TeleportOut) && isCurrentObject(objTeleportNextIndex, ObjID.nObjID_Teleport)) {
                    ForceStop();
                    m_nPosX = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                    m_nPosY = GameWorld.dynamicObjects[objCurrentIndex].m_nPosY;
                    m_nTmpPosX = m_nPosX;
                    m_nTmpPosY = m_nPosY;

                    m_nKeybMode = nModeTeleport;
                    m_blVisible = true;
                    m_blChangeAnimEnable = true;
                    setAnim(c_nAnimID_TeleportIn);
                }
            }
            else if(isCurrentObject(objCurrentIndex, ObjID.nObjID_Cannon)) {
                if(m_nKeybMode == nModeNormal) {
                    m_nKeybMode = nModeCannon;
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent = GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON];
                    GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.Reset();
                    GameWorld.dynamicObjects[objCurrentIndex].m_blActive = true;
                    GameWorld.dynamicObjects[objCurrentIndex].m_nParam = 1;

                    //#if !IMGGROUP_12x12xLimited
                        setAnim( c_nAnimID_CannonCharging );
                    //#endif

                    setCannonMessQueue(LevObj.c_bCannonState_ClimbIn, true);
                }
                else if( m_nKeybMode == nModeCannon ) {
                    int phase = GameWorld.dynamicObjects[objCurrentIndex].m_nParam >> 8;
                    int pow = GameWorld.dynamicObjects[objCurrentIndex].m_nParam & 0xff;
                    if ( phase == LevObj.c_bCannonState_Charging ) {
                        if ( ((++GameWorld.dynamicObjects[objCurrentIndex].m_nParam) & 0xff) > 5 ) {
                            GameWorld.dynamicObjects[objCurrentIndex].m_nParam &= 0xff00;
                            GameWorld.dynamicObjects[objCurrentIndex].m_nParam++;
                        }

                        //#if !IMGGROUP_12x12xLimited
                            animationCurrent.nStateFlg &= ~Animation.cnANIM_STATE_PAUSED;
                        //#endif

                        cannonCurMess = 0;
                        cannonWaitTime = 0;
                        cannonShowTime = 0;
                    }
                    else if ( phase == LevObj.c_bCannonState_Move ) {
                        GameWorld.dynamicObjects[objCurrentIndex].m_nParam = (short)((LevObj.c_bCannonState_Aiming << 8) | pow);
                        GameWorld.dynamicObjects[objCurrentIndex].animationCurrent = GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON];
                        GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.Reset();

                        setCannonMessQueue(LevObj.c_bCannonState_Aiming, true);
                    }
                    else if ( phase == LevObj.c_bCannonState_Aiming ) {
                        int hw = GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.GetCurFrmWidth() >> 1;
                        int x = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                        int y = m_nPosY - GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.GetCurFrmHeight();
                        boolean bl_right = false;
                        switch(GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nCurFrame) {
                            case 1:
                                x -= hw;
                                bl_right = false;
                            break;

                            case 3:
                                x += hw;
                                bl_right = true;
                            break;
                        }

                        //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                            int mw = 3;
                        //#elif IMGGROUP_18x18
                            int mw = 6;
                        //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                            int mw = 8;
                        //#elif IMGGROUP_36x36
                            int mw = 12;
                        //#endif

                        int h = animCannonFlying.GetAnimHeight();
                        
                        if (GameWorld.IsIntersect(x - mw, y - h, x + mw, y, true, bl_right, false, false) != GameWorld.nRet_CantMove) {
                            GameWorld.dynamicObjects[objCurrentIndex].m_nParam = (short)((LevObj.c_bCannonState_Fire << 8) | pow);
                            GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON_FIRE].nStateFlg &= ~Animation.cnANIM_STATE_PAUSED;
                            GameWorld.dynamicObjects[objCurrentIndex].animationList[Constants.ANIMATION_CANNON_FIRE].Reset();
                            GameWorld.dynamicObjects[objCurrentIndex].animationCurrent.nStateFlg &= ~Animation.cnANIM_STATE_PAUSED;

                            cannonShowTime = -1;
                        }
                    }
                }
            }
        }  
    }

    /*
     *
     */
    public static void Draw(Graphics g, int n_scr_x, int n_scr_y) {
        if (m_blVisible) {
            if (animationCurrent != null) {
                Animation item_1 = null;
                Animation item_2 = null;
                if ( m_blDynamite ) item_2 = animItemDynamite;

                if ( m_nPickAxe > 0 ) {
                    item_1 = m_blDirRight ? animItemPickAxeRight : animItemPickAxeleft;
                    if ((m_nPickAxe <= c_nPickAxeFlashTime) && ((m_bLastTimeTick & 1) == 0)) {
                        item_1 = null;
                    }
                }

                if ((item_1 == null) && (item_2 == null)) {
                    animationCurrent.Draw(g, m_nPosX - n_scr_x, m_nPosY + 1 - n_scr_y);
                }
                else {
                    animationCurrent.DrawBefore(g, m_nPosX - n_scr_x, m_nPosY + 1 - n_scr_y, item_1, item_2);
                }
            }
        }
        else {
            if (m_nKeybMode == nModeSlide) {
                int th = PicDrawer.GetPicHeight(PicID.nPicID_slide_t);
                int lh = PicDrawer.GetPicHeight(PicID.nPicID_marv_f1);
                int lw = PicDrawer.GetPicWidth(PicID.nPicID_marv_f1);
                //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                    int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 1;
                    int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 1;
                //#elif IMGGROUP_18x18
                    int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 1;
                    int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 2;
                //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                    int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 2;
                    int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 3;
                //#elif IMGGROUP_36x36
                    int hw = (PicDrawer.GetPicWidth(PicID.nPicID_slide_l_t) >> 1) - 3;
                    int neck = (PicDrawer.GetPicWidth(PicID.nPicID_slide_vt) >> 1) - 4;
                //#endif
                int x;

                // in
                int dy = lh - (m_nPosY - GameWorld.dynamicObjects[objCurrentIndex].m_nPosY + th);
                if (dy > 0) {
                    x = GameWorld.dynamicObjects[objCurrentIndex].m_nPosX;
                    if (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam < x) {
                        x = x + hw - neck;
                    }
                    else if (GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam > x) {
                        x = x - hw + neck;
                    }
                    PicDrawer.DrawPic(g, x - n_scr_x, m_nPosY - lh - n_scr_y, lw, dy, PicID.nPicID_marv_f1, Graphics.HCENTER | Graphics.TOP);
                }

                // out
                dy = m_nPosY - GameWorld.dynamicObjects[objCurrentIndex].m_nParam - th;
                if (dy > 0) {
                    if (dy > lh) {
                        dy = lh;
                    }
                    x = GameWorld.dynamicObjects[objCurrentIndex].m_nAddParam;
                    if (x < GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                        x = x - hw + neck;
                    }
                    else if (x > GameWorld.dynamicObjects[objCurrentIndex].m_nPosX) {
                        x = x + hw - neck;
                    }
                    x = x - n_scr_x - (lw >> 1);

                    int y = GameWorld.dynamicObjects[objCurrentIndex].m_nParam + th - n_scr_y;
                    PicIndex pic_ind = PicDrawer.mIndex[PicID.nPicID_marv_f1];
                    if (MTMCanvas.setClip(g, x, y, lw, dy, false)) {
                        g.drawImage(PicDrawer.mImages[pic_ind.nImgID], x - pic_ind.x, y - pic_ind.y - pic_ind.h + dy, Graphics.LEFT | Graphics.TOP);
                    }
                }
            }
        }
        // cannon help
        if (cannonShowTime > 0) {
            if (cannonShowTime == 1) {
                if (((cannonCurMess + 1) < cannonMessQueue.length) && (cannonMessQueue[cannonCurMess + 1] != -1)) {
                    cannonCurMess++;
                    GameMenu.strToText(cannonMessQueue[cannonCurMess], false);
                    cannonShowTime = c_nMessShowTime;
                }
                else {
                    cannonCurMess = 0;
                    cannonWaitTime = 0;
                }
            }

            //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
                GameMenu.drawText(g, MTMCanvas.width >> 1, 20, Graphics.TOP|Graphics.HCENTER);
            //#elif IMGGROUP_18x18
                GameMenu.drawText(g, MTMCanvas.width >> 1, 30, Graphics.TOP|Graphics.HCENTER);
            //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
                GameMenu.drawText(g, MTMCanvas.width >> 1, 40, Graphics.TOP|Graphics.HCENTER);
            //#elif IMGGROUP_36x36
                GameMenu.drawText(g, MTMCanvas.width >> 1, 60, Graphics.TOP|Graphics.HCENTER);
            //#endif
            cannonShowTime--;
        }
    }

    /*
     *
     */
    public static void setAnim(int n_id) {
        if ((m_blChangeAnimEnable) && (m_nCurAnimID != n_id)) {
            m_nCurAnimID = n_id;
            switch ( m_nCurAnimID ) {
                case c_nAnimID_Idle: {
                    if ( m_blDirRight )
                        animationCurrent = animGoRight;
                    else
                        animationCurrent = animGoLeft;
                    animationCurrent.SetFrame( 0 );
                    animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                    break;
                }

                case c_nAnimID_Go: {
                    if (m_blDirRight)
                        animationCurrent = animGoRight;
                    else
                        animationCurrent = animGoLeft;
                    animationCurrent.nStateFlg &= ~Animation.cnANIM_STATE_PAUSED;
                    break;
                }

                case c_nAnimID_TeleportIn: {
                    animationCurrent = animTeleport;
                    animationCurrent.nStateFlg &= ~Animation.cnANIM_STATE_PLAY_REVERSED;
                    animationCurrent.Reset();
                    break;
                }

                case c_nAnimID_TeleportOut: {
                    animationCurrent = animTeleport;
                    animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PLAY_REVERSED;
                    animationCurrent.Reset();
                    break;
                }

                case c_nAnimID_Jump: {
                    if ( m_blDirRight )
                        animationCurrent = animJumpRight;
                    else
                        animationCurrent = animJumpLeft;
                    animationCurrent.SetFrame( 0 );
                    animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                    break;
                }

                case c_nAnimID_Death: {
                    animationCurrent = animDeath;
                    animationCurrent.Reset();
                    break;
                }

                //#if !IMGGROUP_12x12xLimited
                case c_nAnimID_DropDeath: {
                    animationCurrent = animFallDeath;
                    animationCurrent.Reset();
                    break;
                }

                case c_nAnimID_FireDeath: {
                    animationCurrent = animFireDeath;
                    animationCurrent.Reset();
                    break;
                }

                case c_nAnimID_TODeath: {
                    animationCurrent = animTODeath;
                    animationCurrent.Reset();
                    break;
                }

                case c_nAnimID_Turn: {
                    animationCurrent = animTurn;
                    if ( !m_blDirRight )
                        animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PLAY_REVERSED;
                    else
                        animationCurrent.nStateFlg &= ~Animation.cnANIM_STATE_PLAY_REVERSED;
                    animationCurrent.Reset();
                    break;
                }

                case c_nAnimID_CannonCharging: {
                    if ( m_blDirRight )
                        animationCurrent = animCannonChRight;
                    else
                        animationCurrent = animCannonChLeft;
                    animationCurrent.Reset();
                    animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                    break;
                }
                //#endif

                case c_nAnimID_CannonFlying:
                    animationCurrent = animCannonFlying;
                    animationCurrent.Resume();
                break;

                case c_nAnimID_Fall: {
                    animationCurrent = animFall;
                    break;
                }

                case c_nAnimID_LadderMoving:
                    animationCurrent = animClimbLadder;
                    animationCurrent.Resume();
                break;

                case c_nAnimID_LadderPaused:
                    animationCurrent = animClimbLadder;
                    animationCurrent.nStateFlg |= Animation.cnANIM_STATE_PAUSED;
                break;

                case c_nAnimID_LadderStartFinish:
                    animationCurrent = animLadderStartFinish;
                    animationCurrent.Resume();
                break;
            }
        }
    }

    // Collis ret codes
    public static final int COLLIS_RET_NONE        = 0;
    public static final int COLLIS_RET_STOP        = 1;
    public static final int COLLIS_RET_NO_MOVING   = 2;

    // constants
    public static final int c_nMaxLives       = 3;

    //  Tick() retcodes
    public static final int c_nRetNone        = 0;
    public static final int c_nRetHeroDeath   = 1;

    // Marv's speed
    //#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
        public static final int SPEED_HMOVE       = 4;
        public static final int SPEED_VMOVE       = 3;
        public static final int c_nSpeedJump      = 8;
        public static final int c_nDeadHeight     = 54;
    //#elif IMGGROUP_18x18
        public static final int SPEED_HMOVE       = 6;
        public static final int SPEED_VMOVE       = 4;
        public static final int c_nSpeedJump      = 12;
        public static final int c_nDeadHeight     = 81;
    //#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
        public static final int SPEED_HMOVE       = 8;
        public static final int SPEED_VMOVE       = 5;
        public static final int c_nSpeedJump      = 16;
        public static final int c_nDeadHeight     = 108;
    //#elif IMGGROUP_36x36
        public static final int SPEED_HMOVE       = 12;
        public static final int SPEED_VMOVE       = 8;
        public static final int c_nSpeedJump      = 24;
        public static final int c_nDeadHeight     = 162;
    //#endif
    // animation's states
    public static final int c_nAnimID_None                = 0;
    public static final int c_nAnimID_Idle                = 1;
    public static final int c_nAnimID_Go                  = 3;
    public static final int c_nAnimID_Jump                = 4;
    public static final int c_nAnimID_Fall                = 5;
    public static final int c_nAnimID_Death               = 6;
    //#if !IMGGROUP_12x12xLimited
        public static final int c_nAnimID_DropDeath           = 7;
        public static final int c_nAnimID_FireDeath           = 8;
        public static final int c_nAnimID_TODeath             = 9;
        public static final int c_nAnimID_Turn                = 10;
    //#endif
    public static final int c_nAnimID_TeleportIn          = 11;
    public static final int c_nAnimID_TeleportOut         = 12;
    //#if !IMGGROUP_12x12xLimited
        public static final int c_nAnimID_CannonCharging      = 13;
    //#endif
    public static final int c_nAnimID_CannonFlying        = 14;
    public static final int c_nAnimID_LadderMoving        = 15;
    public static final int c_nAnimID_LadderPaused        = 16;
    public static final int c_nAnimID_LadderStartFinish   = 17;

    // Items params
    public static final int c_nPickAxeTime        = 200;
    public static final int c_nPickAxeFlashTime   = 30;

    // Keyboard mode
    public static final int nModeNormal       = 0;
    public static final int nModeTeleport     = 1;
    public static final int nModeCannon       = 2;
    public static final int nModeCannonFlying = 3;
    public static final int nModeLadder       = 4;
    public static final int nModeLadderStart  = 5;
    public static final int nModeLadderFinish = 6;
    public static final int nModeSlide        = 7;

    private static final byte DIRECTION_MOVE_UP     = -1;
    private static final byte DIRECTION_MOVE_NONE   = 0;
    private static final byte DIRECTION_MOVE_DOWN   = 1;

    // message system params
    private static final int c_nMessShowTime = 75;
    private static final int c_nMessWaitTime = 25;
}
